package com.example.pdf.util;

import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.font.constants.StandardFonts;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.extgstate.PdfExtGState;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;

import java.io.IOException;

/**
 * PDF 水印添加
 *
 * @author mrcode
 * @date 2021/10/22 21:27
 */
public class PdFWatermarkUtil {
    /**
     * 添加文字水印； 默认为居中添加
     *
     * @param watermark
     * @param srcPath   原始 PDF 文件绝对路径
     * @param destPath  添加完水印后的 PDF 存放路径
     */
    public static void addWatermark(TextWatermark watermark, String srcPath, String destPath) throws IOException {
        PdfDocument pdfDoc = new PdfDocument(new PdfReader(srcPath), new PdfWriter(destPath));
        Document doc = new Document(pdfDoc);
        PdfFont font = getPdfFont(watermark.getFontPath());

        // 设置文字水印样式
        final String text = watermark.getText();
        final int fontSize = watermark.getFontSize();
        Paragraph paragraph = new Paragraph(text)
                .setFont(font)
//                 .setFontColor(new DeviceRgb(0, 0, 0))
                .setOpacity(watermark.getOpacity()) // 字体透明度 0-1 完全透明~不透明
                .setFontSize(fontSize); // 字体大小
        final String color = watermark.getColor();
        // 设置 RGB 颜色
        if (color != null) {
            final String[] rgbs = color.split(",");
            final DeviceRgb deviceRgb = new DeviceRgb(
                    Integer.parseInt(rgbs[0].trim()),
                    Integer.parseInt(rgbs[1].trim()),
                    Integer.parseInt(rgbs[2].trim()));
            paragraph.setFontColor(deviceRgb);
        }

        // 获取水印文字宽度
        final float textWidth = font.getWidth(text, fontSize);
        // 文字高度则是字体大小
        final float textHeight = fontSize;
        final int tileMode = watermark.getTileMode();
        final int pageModeOfHorizontalInterval = watermark.getPageModeOfHorizontalInterval() == null ? 50 : watermark.getPageModeOfHorizontalInterval();
        final int pageModeOfVerticalInterval = watermark.getPageModeOfVerticalInterval() == null ? (int) textHeight : watermark.getPageModeOfVerticalInterval();

        for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
            PdfPage pdfPage = pdfDoc.getPage(i);
            // 获取页面大小，考虑页面旋转
            Rectangle pageSize = pdfPage.getPageSizeWithRotation();
            // 当页面有旋转时，内容自动旋转
            pdfPage.setIgnorePageRotationForContent(true);

            // 水印水平垂直居中
            if (tileMode == 1) {
                // 计算添加的位置坐标：这里使用居中位置，水平垂直居中
                float x = (pageSize.getLeft() + pageSize.getRight()) / 2;
                float y = (pageSize.getTop() + pageSize.getBottom()) / 2;

                // 参数分别为：文本、x 坐标、y 坐标、添加到底几页、文本水平对齐方式、文本垂直对齐方式、旋转弧度
                doc.showTextAligned(paragraph,
                        x, // 文本所在 x y 坐标，文字将围绕这个点进行对齐或则旋转
                        y,
                        i, // 添加到 PDF 第几页
                        TextAlignment.CENTER,   // 文本水平对齐方式
                        VerticalAlignment.TOP, // 文本垂直对齐方式
                        // 将 角度 转换为 弧度
                        (float) Math.toRadians(watermark.getRadAngle()));
            } else {
                // 水印按照设置平铺页面

                // 注意这里的坐标点是 文字中心点，所以宽度需要增加文字自己的宽度，否则会重合在一起
                for (float posX = 0f; posX < pageSize.getWidth(); posX = posX + textWidth + pageModeOfHorizontalInterval) {
                    for (float posY = pageModeOfVerticalInterval; posY < pageSize.getHeight(); posY = posY + pageModeOfVerticalInterval) {
                        // 参数分别为：文本、x 坐标、y 坐标、添加到底几页、文本水平对齐方式、文本垂直对齐方式、旋转弧度
                        doc.showTextAligned(paragraph,
                                posX, // 文本所在 x y 坐标，文字将围绕这个点进行对齐或则旋转
                                posY,
                                i, // 添加到 PDF 第几页
                                TextAlignment.CENTER,   // 文本水平对齐方式
                                VerticalAlignment.TOP, // 文本垂直对齐方式
                                // 将 角度 转换为 弧度
                                (float) Math.toRadians(watermark.getRadAngle()));
                    }
                }
            }
        }
        doc.close();
    }

    /**
     * 获取字体，支持 afm、pfm、ttf、otf、woff、woff2 字体，ttc 目前直接报错
     *
     * @param fontPath 字体文件绝对路径，如果为空则返回默认的英文字体
     * @return
     */
    private static PdfFont getPdfFont(String fontPath) throws IOException {
        if (fontPath == null) {
            return PdfFontFactory.createFont(StandardFonts.HELVETICA);
        }
        return PdfFontFactory.createFont(
                fontPath,
                // 水平书写
                PdfEncodings.IDENTITY_H,
                // 是否将字体嵌入到目标文档中: 如果可能，嵌入字体
                PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED);
    }

    /**
     * 添加图片水印； 默认为居中添加
     *
     * @param watermark
     * @param srcPath   原始 PDF 文件绝对路径
     * @param destPath  添加完水印后的 PDF 存放路径
     */
    public static void addWatermark(ImageWatermark watermark, String srcPath, String destPath) throws IOException {
        PdfDocument pdfDoc = new PdfDocument(new PdfReader(srcPath), new PdfWriter(destPath));
        Document doc = new Document(pdfDoc);

        // 创建图片
        ImageData img = ImageDataFactory.create(watermark.getPath());
        float w = img.getWidth();
        float h = img.getHeight();

        // 设置透明度
        PdfExtGState gs1 = new PdfExtGState().setFillOpacity(watermark.getOpacity());

        // 循环添加到每一页的 PDF 中
        for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
            PdfPage pdfPage = pdfDoc.getPage(i);
            // 获取页面大小，考虑页面旋转
            Rectangle pageSize = pdfPage.getPageSizeWithRotation();
            // 当页面有旋转时，内容自动旋转
            pdfPage.setIgnorePageRotationForContent(true);

            // 计算添加的位置坐标：这里使用居中位置，水平垂直居中
            float x = (pageSize.getLeft() + pageSize.getRight()) / 2;
            float y = (pageSize.getTop() + pageSize.getBottom()) / 2;

            // 添加图片水印使用
            PdfCanvas over = new PdfCanvas(pdfDoc.getPage(i));
            over.saveState();
            over.setExtGState(gs1);

            // 添加图片水印：位置水平垂直居中
            over.addImageWithTransformationMatrix(img, w, 0, 0, h, x - (w / 2), y - (h / 2), false);
            over.restoreState();
        }
        doc.close();
    }
}
